package com.dc.di.transport.ibmmq;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXBuilder;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.OMTextImpl;
import org.apache.axiom.om.util.StAXUtils;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
import org.apache.axis2.Constants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.transport.jms.JMSConstants;
import org.pentaho.di.core.logging.LogChannel;
import org.pentaho.di.core.logging.LogChannelInterface;

public class WMQUtils {
	private static final Map<String,String> MQException_Explain = new HashMap<String, String>();
	static {
		MQException_Explain.put("2009", "Connection to queue manager lost.");
		MQException_Explain.put("2059", "Queue manager not available for connection.");
		MQException_Explain.put("2053", "Queue already contains maximum number of messages.");
		MQException_Explain.put("2058", "Queue manager name not valid or not known.");
		MQException_Explain.put("2010", "Message format not valid");
		MQException_Explain.put("2037", "Queue not open for input.");
		MQException_Explain.put("2039", "Queue not open for output.");
		MQException_Explain.put("2036", "Queue not open for browse.");
		MQException_Explain.put("2162", "Queue manager shutting down.");
		MQException_Explain.put("2071", "Insufficient storage available.");
		MQException_Explain.put("2102", "Insufficient system resources available.");
		MQException_Explain.put("2161", "Queue manager quiescing.");
		MQException_Explain.put("2184", "Remote queue name not valid.");
		MQException_Explain.put("2030", "Message length greater than maximum for queue.");
		MQException_Explain.put("2031", "Message length greater than maximum for queue manager.");
		MQException_Explain.put("2018", "Connection handle not valid.");
	}
	
	public static final String ENCODEING_GBK = "GBK";
	
	private static LogChannelInterface log = new LogChannel("WMQUtils");
	public static String getMQException(String errorCode){
		String error_explain = MQException_Explain.get(errorCode);
		if (error_explain == null) 
			error_explain = "can't find error explain,please find error "+errorCode+" in MQ InfoCenter";
		return error_explain;
	}
	public static SOAPEnvelope getSOAPEnvelope(
            String message, MessageContext msgContext, InputStream in)
            throws XMLStreamException {
		SOAPEnvelope envelope = null;
        StAXBuilder builder = null;
		SOAPFactory soapFactory = new SOAP11Factory();
        try {
        	
            XMLStreamReader xmlreader = StAXUtils.createXMLStreamReader(in, ENCODEING_GBK);

            // Set the encoding scheme in the message context
            msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING,ENCODEING_GBK);
            builder = new StAXOMBuilder(xmlreader);
            builder.setOMBuilderFactory(soapFactory);

            String ns = builder.getDocumentElement().getNamespace().getNamespaceURI();
            if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(ns)) {
                envelope = getEnvelope(in, SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
            } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(ns)) {
                envelope = getEnvelope(in, SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
            } else {
                // this is POX ... mark MC as REST
                msgContext.setDoingREST(true);
                envelope = soapFactory.getDefaultEnvelope();
                envelope.getBody().addChild(builder.getDocumentElement());
            }
        } catch (Exception e) {
            log.logDebug("WMQUtils.getSOAPEnvelope", "Non SOAP/XML WMQ message received");
            log.logError("getSOAPEnvelope", e);
            Parameter wrapperParam = msgContext.getAxisService().
                getParameter(JMSConstants.WRAPPER_PARAM);
            QName wrapperQName = (wrapperParam != null ?
                getQName(wrapperParam.getValue()) : JMSConstants.DEFAULT_WRAPPER);

            OMElement wrapper = soapFactory.createOMElement(wrapperQName, null);

            try {
                OMTextImpl textData = (OMTextImpl) soapFactory.createOMText(message);
                wrapper.addChild(textData);
                envelope = soapFactory.getDefaultEnvelope();
                envelope.getBody().addChild(wrapper);

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return envelope;
	}
    public static boolean isWMQService(AxisService service) {
        boolean process = service.isEnableAllTransports();
        if (process) {
            return true;

        } else {
            List transports = service.getExposedTransports();
            for (int i = 0; i < transports.size(); i++) {
                if (WMQConstants.WMQ_TRANSPORT.equals(transports.get(i))) {
                    return true;
                }
            }
        }
        return false;
    }
    private static QName getQName(Object obj) {
        String value;
        if (obj instanceof QName) {
            return (QName) obj;
        } else {
            value = obj.toString();
        }
        int open = value.indexOf('{');
        int close = value.indexOf('}');
        if (close > open && open > -1 && value.length() > close) {
            return new QName(value.substring(open+1, close-open), value.substring(close+1));
        } else {
            return new QName(value);
        }
    }
    private static SOAPEnvelope getEnvelope(InputStream in, String namespace) throws XMLStreamException {

        try {
            in.reset();
        } catch (IOException e) {
            throw new XMLStreamException("Error resetting message input stream", e);
        }
        XMLStreamReader xmlreader = StAXUtils.createXMLStreamReader (in, ENCODEING_GBK);
        StAXBuilder builder = new StAXSOAPModelBuilder(xmlreader, namespace);
        return (SOAPEnvelope) builder.getDocumentElement();
    }
    public static Map<String,String> getProperties(String url) {
    	Map<String,String> env = new HashMap<String,String>();
        int queuePos = url.indexOf("//");
        int propPos = url.indexOf("?");
        env.put("QUEUE", url.substring(queuePos+2,propPos));
        if (propPos != -1) {
            StringTokenizer st = new StringTokenizer(url.substring(propPos + 1), "&");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                int sep = token.indexOf("=");
                if (sep != -1) {
                	env.put(token.substring(0, sep), token.substring(sep + 1));
                } else {
                    continue; // ignore, what else can we do?
                }
            }
        }
        return env;
    }
    public static void main(String[] args) {
    	String target = "wmq://ZHANGJN?HOSTNAME=10.1.140.234&SENDCODE=1381&PORT=1414&CHANNEL=zhangjn&MANAGER=QM_dbserver_2";
    	System.out.println(getProperties(target));
    }
}
